import {assert} from "../../utils/assert";
import {stringUtils} from "../../utils/stringUtils";
import {ScriptRender} from "../../utils/ScriptRender";
import {supportFunction} from "../../utils/supportFunction";
import {MidwareConfig} from "../midware";
import {WekMapPolyFill} from "../../polyfill/WekMapPolyFill";
import jQuery from 'jquery';

//poly fill
if (!window.WeakMap) {
    window.WeakMap = WekMapPolyFill;
}

//样式路径
const _styleAssetPath = new WeakMap();

class StyleManager {

    constructor() {
        if (!StyleManager.instance) {
            this._styleConfig = {};
            this._loadedStyle = {};
            this._courseobjectToSkin = {};
            this._containVersion = false;

            StyleManager.instance = this;
        }

        return StyleManager.instance;
    }

    /**
     * 加载样式配置并转换为更容易处理的结构
     * @param path 样式库配置位置
     * @param file 样式库配置文件
     * @param async 同步读取配置
     * @param version 样式库路径是否包含版本
     */
    loadConfig(path = undefined, file = 'style.config.json', async = true, version = false) {
        if (!supportFunction.isOwnEmptyObject(this._styleConfig)) {
            console.info("style config has been loaded! can't load repeatedly!!");
            return;
        }
        _styleAssetPath.set(this, stringUtils.urlJoin(MidwareConfig.BasePath, MidwareConfig.AssetsBasePath));
        const configPath = stringUtils.urlJoin(MidwareConfig.BasePath, path, file, '?releaseNum=' + MidwareConfig.PlayerReleaseNumber);
        return jQuery.ajax({
            url: configPath,
            dataType: 'json',
            async: async
        }).done(styleConfigs => {
            for (let key in styleConfigs) {
                let config = styleConfigs[key];
                if (config.styles && Array.prototype.isArray(config.styles)) {
                    config.styles.forEach(style => {
                        //设置默认值
                        if (style.default === undefined) {
                            style['default'] = {
                                app: 'pptshell',
                                skin: '__default',
                                language: 'zh_CN'
                            };
                        }
                        let cfg;
                        for (let i = 0, len = style.configs.length; i < len; i++) {
                            cfg = style.configs[i];
                            cfg.link += '?releaseNum=' + MidwareConfig.PlayerReleaseNumber + "";
                        }
                    });
                }
            }
            this._styleConfig = styleConfigs;
            this._containVersion = version;
        }).fail(() => {
            console.warn("can't load style config file!");
        });
    }

    /**
     * 释放颗粒加载的样式
     * @param name 颗粒名称
     */
    releaseStyle(name) {
        for (let key in this._loadedStyle) {
            //找到对应颗粒
            if (key.indexOf(name) === 0) {
                let setting = this._loadedStyle[key];
                if (setting.loaded) {
                    setting.elements.forEach(ele => {
                        ScriptRender.removeStyleElement(ele);
                    });
                    setting.elements = [];
                    setting.loaded = false;
                }
            }
        }
    }

    /**
     * 加载颗粒样式
     * @param name 颗粒名称
     * @param scene 场景名称
     * @param skin 皮肤
     * @param lang 语言
     */
    loadStyle(name, scene, skin, lang) {
        //验证输入参数
        assert(name === undefined, 'the style library name is empty');
        if (!supportFunction.hasProp(this._styleConfig, name)) {
            console.warn('specified courseware object are not configured with style libraries');
            return;
        }
        const styleKey = name + '_' + scene + '_' + skin + '_' + lang;
        if (!supportFunction.hasProp(this._loadedStyle, styleKey)) {
            //还没有提取加载
            this._loadedStyle[styleKey] = {loaded: false, styles: [], elements: []};
            const styles = this._styleConfig[name].styles;
            styles.forEach(style => {
                let filter = {
                    app: scene || style.default.app, skin: skin || style.default.skin,
                    language: lang || style.default.language
                };
                let config = style.configs.find(item => {
                    return item.app === filter.app &&
                        item.skin === filter.skin &&
                        item.language.indexOf(filter.language) >= 0;
                });
                if (config !== undefined) {
                    if (this._containVersion) {
                        //需要包含版本
                        config.link = config.link.insert(config.link.indexOf(style.code) + style.code.length, ('/' + style.version));
                    }
                    this._loadedStyle[styleKey].styles.push(
                        stringUtils.applyTemplate(config.link, {'assets': _styleAssetPath.get(this)}));
                }
            });
        }
        const setting = this._loadedStyle[styleKey];
        if (!setting.loaded && setting.styles.length > 0) {
            setting.styles.forEach(item => {
                const styleEle = ScriptRender.addStyle(item);
                setting.elements.push(styleEle);
            });
            setting.loaded = true;
            this._courseobjectToSkin[name] = styleKey;
        }
    }

    /**
     * 改变颗粒样式
     * @param name 样式名称
     * @param scene 当前场景
     * @param skin 皮肤
     * @param lang 语言
     */
    changeStyle(name, scene, skin, lang) {
        const styleKey = name + '_' + scene + '_' + skin + '_' + lang;
        if (this._courseobjectToSkin[name] === styleKey) {
            console.info("the specified style library configuration has been loaded");
            return;
        }
        //移除已经存在的样式库
        this._removeStyle(this._courseobjectToSkin[name]);
        //加载待加载的样式库
        this.loadStyle(name, scene, skin, lang);
    }

    _removeStyle(styleKey) {
        const setting = this._loadedStyle[styleKey];
        if (setting.loaded) {
            setting.elements.forEach(ele => {
                ScriptRender.removeStyleElement(ele);
            });
            setting.elements = [];
            setting.loaded = false;
        }
    }
}

const styleManager = new StyleManager();
export default styleManager;
